home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1995, Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that the name of Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
- * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
- */
- /*
- * cmapfog.c
- *
- * this sample code shows how to do depthcueing using fog in OpenGL with
- * color index mode. you can use the arrow keys to adjust the start and
- * end of the fog effect, the up-arrow key increments that FOG_START value,
- * the down-arrow key decrements FOG_START. the left arrow key increments the
- * FOG_END value, the righ-arrow decrements it. The 'q' key queries the
- * current FOG_START and FOG_END values. as usual, the 'Esc' key will
- * exit. it should help give you an idea as to how the start and end values
- * for fog will affect your scene as well as how to set up a color ramp
- * and get OpenGL to index into it correctly. the default color ramp
- * is 32 entries wide
- */
-
- #include <GL/glx.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <X11/keysym.h>
-
-
- /*
- * double buffered, color index visual attributes
- */
- static int CIattributes[] = {
- GLX_DEPTH_SIZE, 1,
- GLX_DOUBLEBUFFER,
- None,
- };
-
- /*
- * global stuff
- */
- #define COLOR_OFFSET 97
-
- float MY_FOG_START = 0.0;
- float MY_FOG_END = 20.0;
-
- static long W = 700, H = 700;
- static long size, mode;
-
- Display *dpy;
- Window window;
-
- int rampSize = 32; /* default ramp size, 32 entries */
-
- /*
- * this routine does the actual drawing
- */
- static void DoDisplay(void)
- {
- GLint i, n;
-
- /*
- * enable z buffer depth test
- */
- glEnable(GL_DEPTH_TEST);
- glDepthRange(0, 0xfffff);
- glDepthFunc(GL_LESS);
-
- /*
- * set up projection matrix
- */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-30.0, 50.0, -10.0, 50.0, -50.0, 50.0);
-
- /*
- * set up model view matrix
- */
- glMatrixMode(GL_MODELVIEW);
-
- /*
- * just to make things interesting, push down a matrix and
- * apply a 35 degree rotation on x, y & z axis so that the
- * object drawn has some parts closer, some farther away
- */
- glPushMatrix();
- glRotated(35, 1, 1, 1);
-
- /*
- * clear buffers
- */
- glIndexi(0);
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
-
- /*
- * now, turn on fog, linear fog, set fog start & end values as
- * well as color index to the start of the ramp.
- */
- glEnable(GL_FOG);
- glFogi(GL_FOG_MODE, GL_LINEAR);
-
- /*
- * set GL_FOG_INDEX to the rampSize - 1. this is because say we
- * have 32 entries in our ramp, the fragment color index will be
- * in the range 0 - 31.
- */
- glFogi(GL_FOG_INDEX, rampSize-1);
-
- glFogf(GL_FOG_START, MY_FOG_START);
- glFogf(GL_FOG_END, MY_FOG_END);
-
-
- /*
- * set color to first color in the ramp, the color of our object
- */
- glIndexi(COLOR_OFFSET);
-
- glFrontFace(GL_CW);
-
- /*
- * draw a wire-frame pyramid
- */
- glBegin(GL_LINE_LOOP);
- glVertex3f(0,0,0);
- glVertex3f(40,0,0);
- glVertex3f(20,40,0);
- glEnd();
-
- glBegin(GL_LINE_LOOP);
- glVertex3f(0,0,-40);
- glVertex3f(40,0,-40);
- glVertex3f(20,40,0);
- glEnd();
-
- glBegin(GL_LINE_LOOP);
- glVertex3f(0,0,0);
- glVertex3f(0,0,-40);
- glVertex3f(20,40,0);
- glEnd();
-
- glBegin(GL_LINE_LOOP);
- glVertex3f(40,0,0);
- glVertex3f(40,0,-40);
- glVertex3f(20,40,0);
- glEnd();
-
- glFlush();
- glPopMatrix();
-
- /*
- * let's see what we did...
- */
- glXSwapBuffers(dpy, window);
-
- }
-
- /*
- * convenience function, waits for a window to map
- * so that we don't try to render into a window that
- * hasn't mapped yet.
- */
- static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
- {
- if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
- return GL_TRUE;
- }
- return GL_FALSE;
- }
-
-
-
-
- /*
- * main routine
- */
- int main(long argc, char** argv)
- {
- XVisualInfo *vi;
- Colormap cmap;
- XSetWindowAttributes swa;
- GLXContext cx;
- XEvent event;
- GLboolean needDisplay;
- int i;
- XColor *xc;
- float numEnt;
-
-
-
- /*
- * print out instructions
- */
- fprintf(stderr, "\n cmapfog valid commands: ");
- fprintf(stderr, "\n up-arrow : increment FOG_START ");
- fprintf(stderr, "\n down-arrow : decrement FOG_START ");
- fprintf(stderr, "\n left-arrow : increment FOG_END ");
- fprintf(stderr, "\n right-arrow: decrement FOG_END ");
- fprintf(stderr, "\n 'q' key : query current fog start and end values");
- fprintf(stderr, "\n 'Esc' key : exit ");
-
- fprintf(stderr, "\n ");
-
-
- /*
- * if a ramp size has been entered on the command line,
- * use it, else default to 32 entries
- */
- if (argc > 1)
- rampSize = atoi(argv[1]);
- else {
- fprintf(stderr, "\n using default cmap ramp size of 32.");
- fprintf(stderr, "\n to specify ramp size, run:");
- fprintf(stderr, "\n cmapfog <ramp size>");
- }
-
- if ((rampSize < 1) || (rampSize > 128)) {
- fprintf(stderr, "\n number of color ramp entries must be between 1 - 128\n");
- exit(-1);
- }
-
- fprintf(stderr, "\n ramp size: %d", rampSize);
-
-
- /*
- * connect to display
- */
- dpy = XOpenDisplay(0);
- if (!dpy) {
- fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY"));
- return -1;
- }
-
-
- /*
- * find appropriate visual
- */
- vi = glXChooseVisual(dpy, DefaultScreen(dpy), CIattributes);
- if (!vi) {
- fprintf(stderr, "No appropriate visual on \"%s\"\n",
- getenv("DISPLAY"));
- return -1;
- }
-
-
- /*
- * create a colormap for our window
- */
- cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
- AllocAll);
-
- /*
- * set up attributes and create window
- */
- swa.border_pixel = 0;
- swa.colormap = cmap;
- swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
- | KeyReleaseMask;
- window = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 10, 10,
- W, H,
- 0, vi->depth, InputOutput, vi->visual,
- CWBorderPixel|CWColormap|CWEventMask, &swa);
-
- /*
- * need a gl context to render into. don't forget to make it current!
- */
- cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
- if (!glXMakeCurrent(dpy, window, cx)) {
- fprintf(stderr, "Can't make window current to context\n");
- return -1;
- }
-
-
- /*
- * now for the color ramp. allocate an array of XColor cells and
- * fill them in.
- */
- xc = (XColor *) malloc(sizeof(XColor) * rampSize);
- numEnt = (float) (rampSize-1);
-
- for (i = 0; i < rampSize; i++) {
-
- /* black to white ramp */
-
- xc[i].pixel = i + COLOR_OFFSET;
- xc[i].red = (unsigned short) (65535.0 - (65535.0 * (i / numEnt)));
- xc[i].green = (unsigned short) (65535.0 - (65535.0 * (i / numEnt)));
- xc[i].blue = (unsigned short) (65535.0 - (65535.0 * (i / numEnt)));
- xc[i].flags = DoRed | DoGreen | DoBlue;
- }
-
- /*
- * store ramp into window colormap
- */
- XStoreColors(dpy, cmap, xc, rampSize);
-
- /*
- * tell the window manager to install this colormap for our window
- */
- XSetWMColormapWindows(dpy, window, &window, 1);
-
- /*
- * map window and wait for it to map
- */
- XMapWindow(dpy, window);
- XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
-
- needDisplay = GL_TRUE;
-
- /*
- * now watch for X events
- */
- for (;;) {
- do {
- XNextEvent(dpy, &event);
- switch (event.type) {
-
- case Expose:
- needDisplay = GL_TRUE;
- break;
-
- case ConfigureNotify:
- W = event.xconfigure.width;
- H = event.xconfigure.height;
- needDisplay = GL_TRUE;
- break;
-
- case KeyPress:
- {
- char buf[100];
- int rv;
- KeySym ks;
-
- rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
- switch (ks) {
-
- case XK_Up:
- MY_FOG_START++;
- if (MY_FOG_START == MY_FOG_END) {
- MY_FOG_START--;
- fprintf(stderr, "\n fog start = fog end");
- }
- else {
- needDisplay = GL_TRUE;
- fprintf(stderr, "\n fog start: %f", MY_FOG_START);
- }
- break;;
-
- case XK_Down:
- MY_FOG_START--;
- needDisplay = GL_TRUE;
- fprintf(stderr, "\n fog start: %f", MY_FOG_START);
- break;;
-
- case XK_Left:
- MY_FOG_END++;
- needDisplay = GL_TRUE;
- fprintf(stderr, "\n fog end: %f", MY_FOG_END);
- break;
-
- case XK_Right:
- MY_FOG_END--;
- if (MY_FOG_END == MY_FOG_START) {
- MY_FOG_END++;
- fprintf(stderr, "\n fog end = fog start");
- }
- else {
- fprintf(stderr, "\n fog end: %f", MY_FOG_END);
- needDisplay = GL_TRUE;
- }
- break;
-
- case XK_Q:
- case XK_q:
- fprintf(stderr, "\n\n current fog start: %f", MY_FOG_START);
- fprintf(stderr, " current fog end: %f\n", MY_FOG_END);
- break;
-
- case XK_Escape:
- fprintf(stderr, "\n bye...\n");
- return 0;
- break;
- }
- }
- break;
- }
- } while (XPending(dpy) != 0);
-
- /*
- * redisplay if needed
- */
- if (needDisplay) {
- needDisplay = GL_FALSE;
- DoDisplay();
- }
- }
- }
-